package p11.code;

import java.util.Map;
import java.util.concurrent.*;

public class Memoizer3<A,V> implements Computable<A,V> {

    private final Map<A,Future<V>> cache = new ConcurrentHashMap<>();

    private final Computable<A,V> c;

    public Memoizer3(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V compute(A arg) throws InterruptedException {

        //首先在ConcurrentHashmap中查找键arg对应的值
        Future<V> f = cache.get(arg);

        if(f == null) {
            Callable<V> eval = () -> c.compute(arg);
            FutureTask<V> ft = new FutureTask<V>(eval);
            //V putIfAbsent(K key, V value)
            // 如果指定的键尚未与某个值关联(或映射为null)，则将其与给定值关联并返回null，否则返回当前值。
            f = cache.putIfAbsent(arg,ft);//原子方法，避免插入相同的键值
            if(f == null) {
                f = ft;
                ft.run();
            }
        }
        try{
            return f.get();//这里返回计算结果
        }catch(ExecutionException e) {
            throw new InterruptedException();
        }

    }

}
